Digital Symphony revisions:
===========================
1) 12 Mar 1993 (DS 1.20, DSymPlay 1.01)
   ------------------------------------
   Filetypes SySample and Symphony are now able to store 8-bit linear sample
   data.

2) 30 Mar 1994 (DS 1.30, DSymPlay 1.30)
   ------------------------------------
   Filetypes SySample and Symphony are now able to store 16-bit linear sample
   data.
   New compression scheme introduced.
   We now play tunes at nearly exactly the speed an Am*ga does.

3) 01 Sep 1994 (DS 1.31, DSymPlay 1.30)
   ------------------------------------

4) 16 Jan 1995 (DS 1.31, DSymPlay 1.40)
   ------------------------------------
5) 23 Oct 1996 (DS 1.31, DSymPlay 1.41)
   ------------------------------------

Latest versions:
================
DSym_Play module: 1.41
Digital Symphony: 1.31
Symphony file: 1 (from DS 1.30 on)
SySample file: 1 (from DS 1.30 on)
Patterns file: 0

Major changes in DSymPlay from version 1.10 on:
===============================================
- Dynamic choice of the fastest routine given the processor (ARM 2 or >2).
- The load routine didn't release the unpacking buffer (32K) after
  loading a packed song. Works now.
- Changed the specs of the CutNote SWI, sorry!
- StrongARM compatible


This file contains two main parts:
==================================

   I. Effects commands and music files formats.
  II. SWI's and commands of the Digital Symphony players.


   ======================================================================
   PART I : Effect commands and music file formats of some music programs
   ======================================================================

1.1. Amiga ProTracker V1.1B Effect Commands
     --------------------------------------
     (x-y,z) indicates z is done if value not in the range x to y inclusive.
     <command number in hex> <effect value in hex>

     0 xy Normal play or Arpeggio.
          x: first halfnote to add to pitch
          y: second halftone to add to pitch

     1 xx Slide Up.
          xx: pitch increase step

     2 xx Slide Down.
          xx: pitch decrease step

     3 xx Tone Portamento. 
          xx: pitch slide speed (0 for previous speed)

     4 xy Vibrato.
          x: pitch change speed (0 for previous speed)
          y: pitch change depth (0 for previous depth)

     5 xy Tone Portamento + Volume Slide.
          x: volume increase step (priority)
          y: volume decrease step

     6 xy Vibrato + Volume Slide.
          x: volume increase step (priority)
          y: volume decrease step

     7 xy Tremolo.
          x: volume change speed (0 for previous speed)
          y: volume change depth (0 for previous depth)

     8 xx Not used.

     9 xx Set Sample Offset.
          xx: offset in sample DIV 256 (loop restarted if illegal)
              0 for previous offset

     A xy Volume Slide.
          x: volume increase step (priority)
          y: volume decrease step

     B xx Position Jump.
          xx: song position (0-127, masked, 0 if illegal)

     C xx Set Volume.
          xx: volume (0-64,rounded). Linear.

     D xy Pattern Break.
          10*x+y: position to jump to in next pattern (0-63, 0)

     E 0x Set Filter.
          x: filter on (0) or filter off (1) (or power LED on/off)

     E 1x Fine Slide Up.
          x: value to add to pitch

     E 2x Fine Slide Down.
          x: value to subtract from pitch

     E 3x Glissando Control.
          x: on (1) or off (0) (use with Tone Portamento)
          When off, the slide is smooth else from halfnote to halfnote

     E 4x Set Vibrato Waveform.
          x: sine (0), ramp down (1), square (2)
             bit 2 is off if wave form has to be restarted each note

     E 5x Set Fine Tune.
          x: new fine tune value

     E 6x Jump to Loop.
          x: jump to loop, play x times
             if 0, the loop start is set to the current pattern position

     E 7x Set Tremolo Waveform.
          x: sine (0), ramp down (1), square (2)
             bit 2 is off if wave form has to be restarted each note

     E 8x Not used.

     E 9x Retrig Note.
          x: retrig note each (more or less) x vblanks

     E Ax Fine Volume Slide Up.
          x: value to add to volume

     E Bx Fine Volume Slide Down.
          x: value to subtract from volume

     E Cx Note Cut.
          x: cut note after x vblanks (volume is only set to 0)

     E Dx Note Delay.
          x: number of vblanks for note delay

     E Ex Pattern Delay.
          x: delay pattern x notes

     E Fx Invert Loop.
          x: speed
             if 0, it's turned off
          Care must be taken using it: it inverts the sign of sample data
          inside sample loop, one byte each vblank

     F xx Set Speed.
          In CIA mode (recommended and most usual):
              xx: speed (1-31,ignored) or tempo (32-255)
                  Tempo unit: 1/24th vblanks per minute (defaults to 125)
          In VBlank mode:
              xx: speed (1-255,ignored)

1.2. Archimedes Tracker V1.0+++ Effect Commands
     ------------------------------------------                    
     (x-y,z) indicates z is done if value not in the range x to y.
     <command character> <command number in hex> <effect value in hex>

     0 00 xy Normal play or Arpeggio.
             x: first halfnote to add
             y: second halftone to subtract

     1 01 xx Slide Up.
             xx: pitch increase step (4 bits?)

     2 02 xx Slide Down.
             xx: pitch decrease step (4 bits?)
                                         
     B 0B xx Break Pattern.

     E 0E xy Set Stereo.
             y: stereo position (1-7,ignored). 1=left 4=center 7=right
             
     G 10 xx Volume Slide Up.
             xx: speed (4 bits?)

     H 11 xx Volume Slide Down.
             xx: speed (4 bits?)

     J 13 xx Position Jump.
             xx: song position (0-127,masked)

     L 15 xy Line Jump. (not in manual)
             Jump to line 10*x+y in same pattern. (10*x+y>63 ignored)

     S 1C xy Set Speed.
             y: speed (1-15,ignored)

     V 1F xx Set Volume.
             xx: volume (0-255). Logarithmic.

1.3. Archimedes Symphony V1.00 Effect Commands
     -----------------------------------------
     (x-y,z) indicates z is done if value not in the range x to y.
     <command number in hex> <effect value in hex>

     00 xyz Normal play or Arpeggio + Volume Slide Up.
            x: volume increase step
            y: first halfnote to add
            z: second halftone to add

     01 xyy Slide Up + Volume Slide Up.
            x: volume increase step
            yy: pitch increase step

     02 xyy Slide Down + Volume Slide Up.
            x: volume increase step
            yy: pitch decrease step

     03 xyy Tone Portamento. 
            yy: pitch slide speed (0 for previous speed)

     04 xyz Vibrato.
            y: pitch change speed (0 for previous speed)
            z: pitch change depth (0 for previous depth)

     05 xyz Tone Portamento + Volume Slide.
            y: volume increase step (priority)
            z: volume decrease step

     06 xyz Vibrato + Volume Slide.
            y: volume increase step (priority)
            z: volume decrease step

     07 xyz Tremolo.
            y: volume change speed (0 for previous speed)
            z: volume change depth (0 for previous depth)

     09 xxx Set Sample Offset.
            xxx: offset in sample DIV 128 (loop restarted if illegal)
                 0 for previous offset

     0A xyz Volume Slide + Fine Slide Up.
            x: value to add to pitch
            y: volume increase step (priority)
            z: volume decrease step

     0B xxx Position Jump.
            xxx: song position (0 if illegal)

     0C xyy Set Volume.
            yy: volume (0-64,rounded). Linear.

     0D xyy Pattern Break.
            yy: break position in next pattern (0-63, 0)

     0E xxx Not used.

     0F xxx Set Speed.
            xxx: speed (1-4095,ignored). Default is 6

     10 xxy Filter Control. (Not implemented)
            y: filter on (0) or filter off (1)

     11 xyy Fine Slide Up + Fine Volume Slide Up.
            x: value to add to volume
            yy: value to add to pitch

     12 xyy Fine Slide Down + Fine Volume Slide Up.
            x: value to add to volume
            yy: value to subtract from pitch

     13 xxy Glissando Control.
            y: on (1) or off (0) (use with Tone Portamento)
            When off, the slide is smooth else from halfnote to halfnote

     14 xxy Set Vibrato Waveform.
            y: sine (0), ramp down (1), square (2)
               bit 2 is off if wave form has to be restarted each note

     15 xxy Set Fine Tune.
            y: new fine tune value

     16 xxx Jump to Loop.
            xxx: jump to loop, play xxx times
                 if 0, the loop start is set to the current pattern position

     17 xxy Set Tremolo Waveform.
            y: sine (0), ramp down (1), square (2)
               bit 2 is off if wave form has to be restarted each note

     19 xxx Retrig Note.
            xxx: retrig note each (more or less) xxx vblanks

     1A xyy Fine Slide Up + Fine Volume Slide Down.
            x: value to subtract from volume
            yy: value to add to pitch

     1B xyy Fine Slide Down + Fine Volume Slide Down.
            x: value to subtract from volume
            yy: value to subtract from pitch

     1C xxx Note Cut.
            xxx: cut note after xxx vblanks (volume is only set to 0)

     1D xxx Note Delay.
            xxx: number of vblanks for note delay

     1E xxx Pattern Delay.
            xxx: delay pattern xxx notes

     1F xxy Invert Loop.
            y: speed
               if 0, it's turned off
               Care must be taken using it: it inverts the sign of sample
               data inside sample loop, one byte each vblank

     20 xyz Normal play or Arpeggio + Volume Slide Down.
            x: volume decrease step
            y: first halfnote to add
            z: second halftone to add

     21 xyy Slide Up + Volume Slide Down.
            x: volume decrease step
            yy: pitch increase step

     22 xyy Slide Down + Volume Slide Down.
            x: volume decrease step
            yy: pitch decrease step

     2A xyz Volume Slide + Fine Slide Down.
            x: value to subtract from pitch
            y: volume increase step (priority)
            z: volume decrease step

     2B xyy Line Jump.
            yy: Line to jump to in same pattern. (0-63, 0)

     2F xxx Set Tempo.
            xxx: new tempo value (1-4095,ignored).
                 Unit: 1/20th vblanks per second (defaults to 1000)

     30 xxy Set Stereo.
            if y and 7 =0 then xx = stereo position (0-127 is 0 to 127,
                                    129-255 is -1 to -127, 128 ignored)
            if y and 7 >0 then y = stereo position (1-7,ignored).
                               1=left 4=center 7=right

     31 xxx Song Upcall.
            The CPU performs a linked branch to the song upcall vector.
            The routine linked to that vector can corrupt all registers
            and must preserve SVC mode on return using MOVS PC,R14
            On entry registers contain the following:
            R0= xxx parameter
            R4= full note address + 4
            R5= voice number (0 to 7)

     32 xxx Unset Sample Repeat.
            The sample continues to be played until it ends, but without loops

2.1. Amiga ProTracker V1.1B Song/Module Format (Filetype &001)
     ---------------------------------------------------------
     Rem: files handled by Amiga ProTracker, NoiseTracker, SoundTracker,
          IntuiTracker, ...

     Offset  Bytes  Description
     ------  -----  -----------
        0     20    Songname. Trailing null bytes at the end.

     Information for sample 1-31:

     Offset  Bytes  Description
     ------  -----  -----------
       20     22    Samplename. Pad with null bytes.
       42      2    Length DIV 2. 
       44      1    Lower four bits: finetune value (signed 4 bits)
                    Upper four bits: not used (should be 0).
       45      1    Volume for sample 1. Range is &00-&40 (0-64).
       46      2    Repeat offset DIV 2.
       48      2    Repeat length DIV 2.

     Information for the next 30 samples starts here. It's just like the
     info for sample 1.

     Offset  Bytes  Description
     ------  -----  -----------
       50     30    Sample 2...
       80     30    Sample 3...
        .
        .
        .
      890     30    Sample 30...
      920     30    Sample 31...

     Offset  Bytes  Description
     ------  -----  -----------
      950      1    Songlength (1-128).
      951      1    Well... this little byte here is set to 127, so that old
                    trackers will search through all patterns when loading.
                    NoiseTracker uses this byte for restart, but we don't.
      952    128    Song positions 0-127. Each hold a number from 0-63 that
                    tells the tracker what pattern to play at that position.
     1080      4    The four letters "M.K." - This is something
                    Mahoney & Kaktus inserted when they increased the number
                    of samples from 15 to 31. If it's not there, the
                    module/song uses 15 samples or the text has been removed
                    to make the module harder to rip. Startrekker puts
                    "FLT4" or "FLT8" there instead. "M&K!" may be present,
                    too.

     Offset  Bytes  Description
     ------  -----  -----------
     1084    1024   Data for pattern 00.
        .
        .
        .
     xxxx  Number of patterns stored is equal to the highest pattern number
           in the song position table (at offset 952-1079).

     Each note is stored as 4 bytes, and all four notes at each position in
     the pattern are stored after each other.

     Position          Notes data
     -------- ------------------------------ 
        00    chan 1  chan 2  chan 3  chan 4
        01    chan 1  chan 2  chan 3  chan 4
        02    chan 1  chan 2  chan 3  chan 4
       etc.

     Info for each note:
     -------------------      
     bits 24-31: effect value (0-255).
          20-23: lower 4 bits of sample number (0-15).
          16-19: effect command number (0-15).
           8-15: lower 8 bits of note period (0-255).
           4- 7: upper 4 bits of sample number (0-1).
           0- 3: higher 4 bits of note period (0-3).

     Period table for Tuning 0, normal:
     ----------------------------------
       C-1 to B-1 : 856,808,762,720,678,640,604,570,538,508,480,453
       C-2 to B-2 : 428,404,381,360,339,320,302,285,269,254,240,226
       C-3 to B-3 : 214,202,190,180,170,160,151,143,135,127,120,113

     To determine what note to show, scan through the table until you find
     the same period as the one in the note. Use the index to look up in
     a notenames table.

     This is the data stored in a normal song. A packed song starts with the
     four letters "PACK".

     In a module, all the samples are stored right after the pattern data.
     To determine where a sample starts and stops, you use the sample info
     structures in the beginning of the file (from offset 20). Their format
     is linear signed.

     ProTracker CIA (Complex Interface Adapter) Timer Tempo Calculations
                                      AMIGA
     -------------------------------------------------------------------
     Fcolor                        = 4.43361825 MHz (PAL color carrier freq)
     CPU Clock   = Fcolor * 1.6    = 7.0937892  MHz
     CIA Clock   = CPU Clock / 10  = 709.37892  kHz
     50 Hz Timer = CIA Clock / 50  = 14187.5784
     Tempo num.  = 50 Hz Timer*125 = 1773447

     For NTSC: CPU Clock = 7.1590905 MHz --> Tempo num. = 1789773

      To calculate tempo we use the formula: TimerValue = 1773447 / Tempo
      The timer is only a word, so the available tempo range is 28-255 (++).
      Tempo 125 will give a normal 50 Hz timer (VBlank).

      A normal ProTracker VBlank song tempo can be calculated as follows:
      We want to know the tempo in BPM (Beats Per Minute), or rather quarter-
      notes per minute. Four notes makes up a quarternote.
      First find interrupts per minute: 60 seconds * 50 per second = 3000
      Divide by interrupts per quarter note = 4 notes * speed
      This gives: Tempo = 3000/(4*speed)
      Simplified: Tempo = 750/speed
      For a normal song in speed 6 this formula gives: 750/6 = 125 BPM
      
      Note: The mentioned 50 Hz quantities are rather inaccurate since the
            vblank frequency is exactly 49.9 Hz!

2.2. Archimedes Tracker V1.0+++ File Formats
     ---------------------------------------
     
     Sample chunk format
     -------------------
     This is the component of a Tracker sample file (Filetype &CB5).
     
       Field length Contents
       ------------ --------
          4 bytes   The string "SAMP"
          4 bytes   Chunk length (i.e. total size -8)
          4 bytes   The string "SNAM"
          4 bytes   Sample name length (20)
         20 bytes   Sample name padded with zero's
          4 bytes   The string "SVOL"
          4 bytes   Value 4
          4 bytes   Sample volume (0-255). Logarithmic
          4 bytes   The string "SLEN"
          4 bytes   Value 4
          4 bytes   Sample length (multiple of 4 otherwise Tracker crashes!)
          4 bytes   The string "ROFS"
          4 bytes   Value 4
          4 bytes   Repeat offset
          4 bytes   The string "RLEN"
          4 bytes   Value 4
          4 bytes   Repeat length
          4 bytes   The string "SDAT"
          4 bytes   Sample length (multiple of 4): xx
         xx bytes   Sample data in logarithmic format

       Note: the manual states that not all sub-chunks may be present. But
             until now they've always been there.

     Pattern chunk format
     --------------------
     This is the component of a Tracker pattern file (Filetype &FF1).
     
       Field length Contents
       ------------ --------
          4 bytes   The string "PATT"
          4 bytes   Chunk length (i.e. number of voices * 256 - the manual
                    says it's always 2048, that's false! ): xx
         xx bytes   Notes

         Each note is stored as 4 bytes, and all x notes at each position in
         the pattern are stored after each other.
     
         Position         Notes data
         -------- ---------------------------
            00    chan 1  chan 2  ...  chan x
            01    chan 1  chan 2  ...  chan x
            02    chan 1  chan 2  ...  chan x
           etc.

         Info for each note:
         -------------------      
         bits 24-31: note number (0-36).
              16-23: sample number (0-36).
               8-15: effect command number.
               0- 7: effect value (0-255).
     
         Note numbers table:
         -------------------
           C-1 to B-1 : 01 to 12
           C-2 to B-2 : 13 to 24
           C-3 to B-3 : 25 to 36

     Module format
     -------------
     This is the format of a Tracker module file (Filetype &CB6).
     
       Field length Contents
       ------------ --------
          4 bytes   The string "MUSX"
          4 bytes   Chunk length (i.e. total size -8)
          4 bytes   The string "TINF"
          4 bytes   Value 4
          4 bytes   Date of version in BCD format: YYYYMMDD (bytes 1 to 4)
          4 bytes   The string "MVOX"
          4 bytes   Value 4
          4 bytes   Number of voices (1-8)
          4 bytes   The string "STER"
          4 bytes   Value 8
          8 bytes   Default stereo positions for 8 channels. See the command.
          4 bytes   The string "MNAM"
          4 bytes   Tune name length (32)
         32 bytes   Tune name padded with zero's
          4 bytes   the string "ANAM"
          4 bytes   Author name length (32)
         32 bytes   Author name padded with zero's
          4 bytes   the string "MLEN"
          4 bytes   Value 4
          4 bytes   Tune length (1-128)
          4 bytes   the string "PNUM"
          4 bytes   Value 4
          4 bytes   Number of defined patterns (1-64)
          4 bytes   the string "PLEN"
          4 bytes   Value 64
         64 bytes   Length of each pattern (0-64)
          4 bytes   the string "SEQU"
          4 bytes   Value 128
        128 bytes   pattern number to be played at each position (0-63)

       This is followed by a pattern chunk for each defined pattern.
       After that, there is a sample chunk for each of the 36 samples.

       Note that such a file can contain more than one module (MUSX chunk)
       but practically it's very rare and not easy to handle...

       Such a format for a music module is a bit silly since nearly all
       chunks have a constant length.
   
2.3. Archimedes Symphony Module/Song Format
     --------------------------------------
     Such tunes are composed of a list of positions which refer to the
     pattern that has to be played through a given channel at that song
     position. It's possible to play nothing instead of a pattern.

     The ranges are as follows:
     --------------------------
     Voices: 1 to 8
     Tune length: 0 to 4096 (&1000)
     Pattern number: 0 to 4095 (&FFF)
     
     A pattern is composed of 64 notes.

     Each note is stored as 4 bytes (A 32 bit-word), and of course all notes
     are stored after each other.

     Position Notes data
     -------- ----------
        00      chan i
        01      chan i
        02      chan i
       etc.
     
     Info for each note:
     -------------------
     bits 20-31: effect value (0-4095).
          14-19: effect command number (0-63).
          13-13: not used for now (should be 0).
           6-12: sample number (0-63).
           0- 5: note number (0-36).

     Note numbers table:
     -------------------
       C-1 to B-1 : 01 to 12
       C-2 to B-2 : 13 to 24
       C-3 to B-3 : 25 to 36

     Note: the use of [x,y] in the following specs refers to the revision
           number x and file version y in which the feature first appeared
           (see top of this file)
     Note2: Any program that would like to read Symphony files should test
            the version number and give an error if greater or equal to 10.
            The difference between version 0 and 1 is that a version 1 file
            MAYBE uses the new packing methods as standard. So read the file
            and check if you know the packing methods used.
     Note3: You may notice that the space taken by a soundtrack can be
            computed without reading the whole file.

     Sample file format (Filetype &10A: SySample)
     --------------------------------------------
       Field length Contents
       ------------ --------
          8 bytes   The string "BASSSAMP". Byte value= ASCII code - 64
          1 byte    Version number (currently 1)
          1 byte    Name length: xx
         xx bytes   Name
          3 bytes   Length DIV 2 (length= number of samples, not bytes)
          3 bytes   Repeat offset DIV 2
          3 bytes   Repeat length DIV 2
          1 byte    Packing method
         sy bytes   Data:
                    Packing=0 : 8-bit logarithmic (sy=length)
                    Packing=1 : 13-bit LZW applied to linear sample data
                                differences (sy multiple of 4)
                    Packing=2 : 8-bit linear signed (sy=length)       [1,0]
                    Packing=3 : 16-bit linear signed (sy=length*2)    [2,1]
                                (little endian)
                    Packing=4 : SigmaDelta compression applied to     [2,1]
                                linear sample differences
                    Packing=5 : SigmaDelta compression applied to     [2,1]
                                logarithmic sample differences
        0-3 bytes   Zero's to fill last file word

     Pattern file format (Filetype &FFD: Data)
     -----------------------------------------
       Field length Contents
       ------------ --------
          8 bytes   The string "BASSPTRN". Byte value= ASCII code - 64
          1 byte    Version number (currently 0)
          1 byte    Contents: 0 for a sequence, 1 for some patterns
        0-1 byte    Number of sequence lines (only if Contents=0): z
          2 bytes   Length: number of sequence positions
                    or number of patterns: xx
         yy bytes   Data:
                    Contents=0 : For each line
                                     For xx positions
                                         Pattern number (2 bytes each)
                                 (yy=2*xx*z)
                    Contents=1 : patterns data (yy=256*xx)

     Module/Song file format (Filetype &10B: Symphony)
     -------------------------------------------------
       Field length Contents
       ------------ --------
          8 bytes   The string "BASSTRAK". Byte value= ASCII code - 64
          1 byte    Version number (currently 1)
          1 byte    Number of voices (1 to 8): z
          2 bytes   Track length in positions: y (0 to &1000)
          2 bytes   Number of defined patterns: p (0 to &1000)
          3 bytes   Information text length: il

          For the 63 samples, we have:

       (  1 byte    Sample name length: sn
       (            (bit 7 set if all its data is blanked: lengths, vol, ft)
       (            (bit 6 reserved => mask out to read / write 0)
       (  3 bytes   Sample length DIV 2 (length= number of samples, not bytes)

          1 byte    Track name length: x
          x bytes   Track name
          8 bytes   Effects allowed table. 1 bit per effect (0=no, 1=allowed)
      If y>0 then
        ( 1 byte    Packing system for sequence (0= not packed, 1= packed)
        ( s bytes   Sequence data:
        (           Packing=0 : For each position
        (                           For each voice
        (                               Pattern number (2 bytes)
        (                       (s= 2*y*z)
        (           Packing=1 : 13-bit LZW applied to overall sequence data
        (                       (s multiple of 4)

      If p>0 then
        ( For each pk-pattern chunk (all 2000 patterns but the last):
        (       1 byte  Packing system for chunk (0= not packed, 1= packed)
        (       b bytes Pattern data:
        (               Packing=0 : For each pattern
        (                             For each pattern position (0 to 63)
        (                               Full note value (1 word)
        (                           (b= 4*64*pk)
        (               Packing=1 : 13-bit LZW applied to chunk data
        (                           (b multiple of 4)

          For the 63 samples, we have:

       ( sn bytes   Sample name
       (  3 bytes   Sample repeat offset DIV 2
       (  3 bytes   Sample repeat length DIV 2
       (  1 byte    Sample volume (0 to 64)
       (  1 byte    Sample fine tune (-8 to 7)
       (  1 byte    Packing system for sample (see sample file format)
       (
       ( If sample length>0 then
       (   ( sy bytes Data: see sample file format above

      If il>0 then
        ( 1 byte    Packing system for information text
        (           (0= not packed, 1= packed)
        ( i bytes   Information text:
        (           Packing=0 : Text (i=il)
        (           Packing=1 : 13-bit LZW applied to information text
        (                       (i multiple of 4)

        0-3 bytes   Zero's to fill last file word


    Notes about compression algorithms:

    - Sample differences are computed like this:
      Init: x=0; p=sample start
      Loop: difference= value(p)-x; x= value(p); inc(p)
    - The 13-bit LZW compression scheme uses 256/257 as restart/end code.
      Applied on signed linear sample deltas.
    - The SigmaDelta compression is rather too complex to explain here!
      Applied on unsigned linear or unsigned logarithmic sample deltas.

    Maybe next time we'll provide some algorithms...
    

        =========================================================
        PART II : Digital Symphony SWI's and commands information
        =========================================================

The following explains the functionalities used in the 1 music-player module
(the one generated by the Digital Symphony application) and in the
multi music player module (files DSymPlay and DSymPlayA3). The file DSymPlayA3
only differs from the file DSymPlay in that only the routines used whenever
a cached processor (e.g. ARM3) is detected are present in it, so you gain
some Kbytes space (~16K) but have slower routines when used with non-cached
processors (e.g. ARM2, ARM250).

THESE MODULES ARE FREEWARE. If you use it in a NON COMMERCIAL program (we
strongly encourage it) then all we ask is:
  - In all cases, give some credits to BASS for the playroutine.
  - If the play module stays as a stand-alone module in your app directory,
    then include this text file unaltered too.
If you wish to use them in some commercial software then contact
Oregan Developments for an agreement. See the end of this file for addresses.

Now more technical details.

In order to keep the code size low and the whole CLI command names clean, this
player only offers SWI's. But hopefully a CLI command gives access directly
to these SWI's for the CLI user.

Nearly all SWI's should never be used while interrupting the player routine
(i.e. they're not reentrant). See the SWI that allows to know if the player
routine has been interrupted or not.

You can call a SWI via this * command:

  *DSym <SWI name> [<R0 value> [<R1 value> [<...>]]]

  Of course you can't get results back this way.
  The unspecified values are set to 0 before calling the corresponding SWI.

  A value may be:
    - Any string readable by the OS_ReadUnsigned SWI (see the PRM's).
    - The latter string preceeded by the minus sign for a negative number.
  You can specify a pointer to a string (i.e. when a file name is required)
  only for R0 value: just put the string between quotes.

Some examples:
  Set the overall volume to 64: *DSym Vol 64
  Load file $.MegaMix: *DSym Load "$.MegaMix"
  Set stereo of channel 2 to -127: *DSym Stereo 2 -&7F

Instead of installing the player module in RMA (that requires to ensure
there's enough memory free in RMA, very annoying in demos), you could
directly patch the module into your code. There are 2 ways to do this:

 - Link it to modules chain in RMA using OS_Module 10 (See the PRM's). The
   SWI's are always available. Don't forget to kill it before returning to
   desktop!

 - Don't link to other modules. The SWI's are not directly available.
   Let's assume ModStart to be the start address of the player module in
   your code. First you must call (ModStart+(ModStart!4)) like RISC OS
   would do when loading a module. Now you can use SWI's by calling a
   special routine with R11 containing the SWI number. For example, set the
   volume to 64 with:

               MOV R0,#64        ; SWI parameter
               MOV R11,#2        ; SWI number
               BL  ModStart+44   ; Note: need NOT be in SVC mode

   Finally don't forget to call (ModStart+(ModStart!8)) before your
   program exits.


The advantages of using a generated 1 music-player are as follows:
  - Only the useful routines are included. E.g. the rather big loader routine
    is not included.
  - The tune data is arranged to get more efficient results through
    compaction. In fact, samples are stored as linear deltas.
  - Several parameters can be set by default at module installation, such as
    looping, play or not when module installed...

Also an advantage in the multi music-player from version 1.40 on:
    At module's installation (or song loading for the multi-player), the
    samples data are scaled to the current configured volume of the machine.
    This gives more chances that the efficient sound buffer filling routines
    in the case of no scaling are used. It's of no help if the global volume
    is not at maximum or a sample is not played at full volume.
    WARNING here: when using the InstrData SWI, the newly installed sample
    is scaled too, so avoid calling twice with exactly the same parameters
    without refreshing the real sample data!

The SWI's allow you to play tunes in your own programs and making sound
effects. While the tune is playing you can make additional sound effects
(produce 'custom notes') in the same way the tune does. In fact, you could
play a tune by producing notes stored in your own tables.
If you'd like to play your notes while the tune is playing, you can do it
on the voices used by the tune, but with some tunes there can be some clashes
with samples and notes (this is ONLY a matter of nice sound and NOT a matter
of bugged routines). So it's preferable to play them on the free voices
(the ones with the highest numbers). For example, with a tune with 3 rows
in its sequence and 4 configured voices, you could safely play your notes on
the 4th voice.

Useful example:
---------------
Prototype for playing a song in a usual program:

    SYS"DSym_Load","<Prog$Dir>.Music" :REM Load song in RMA
    SYS"DSym_RestartSong"             :REM Start playing
    REPEAT
    REM Main loop
    UNTIL exit%
    FOR v%=64 TO 0 STEP -1            :REM Fade out
      SYS"DSym_Vol",v%
      WAIT
    NEXT
    *RMKill DSymphonyPlayer

To stop a tune: SYS"DSym_Pause"
To continue after a stop: SYS"DSym_TuneControl",1 or SYS"DSym_RestartSong" to
restart.

Some other possible effects:
  - Engine noises, changing volume and finetune (see effects 11 & 12).
  - Manipulate a lot of samples without loading new tunes, using the InstrData
    SWI.
  - ...

More technical details:
-----------------------
SWI Chunk name: DSym
SWI Chunk base number: &45880 (allocated from Acorn)

Should work on A5000's and some VIDC enhancers (i.e. no pitch bending)
without any additional code. See SWI to set hardware speed.

SWI DSym_Load does not work in the 1 music-player.

The player can only load Digital Symphony format files because it would eat
too much memory (makes me think of other players...). It was designed to
be as 'simple' as possible. It cannot read 16-bit samples.

The player does NOT use the VIDC pointer.

The player does NOT use WAIT's.

The player does use OS_ReadMonotonicTime only:
  - When calling DSym_Configure, DSym_Load or the module finalisation entry.
  - In the buffer filling routine when in 'auto speed' mode (in order to
    'guess' the current VIDC speed) (see SWI HardSpeed)
So let the interrupt for the corresponding timer enabled in those cases.

The FillAddress SWI allows you to know the address of the buffer filling
routine (you could get it with Sound_Configure but it's easier here).
If you feel pretty good you could then call it yourself instead of RISC OS
each time a sound interrupt occurs. You must call DSym_Configure at least
once before using the filling routine.

The specs for the filling routine:

   Entry: R12 points to buffer to fill (word-aligned, length=1664 bytes)
          Processor in IRQ mode
          IRQ disabled
   Exit:  R0-R12,R14 and flags corrupted
          Processor in IRQ mode
          IRQ disabled
          Buffer filled for the number of configured voices (208 bytes/voice)
   The routine enables IRQ's during its work.

You are expected to make no mistakes when passing parameters to SWI's. If
you do, it's possible that the machine locks up! (Remember: the player is
powerful but simple)

Note: There are two SWI's to set the stereo positions. A front-end
      application that sets the current stereo should set the DEFAULT stereo
      too.
Note2: In the following specs, no reference to a register on exit means
       it is preserved.
Note3: It is recommended that you set the sample quality (SampleRate SWI)
       to something other than the default 24. 24 is usually not convenient
       when CPU power is needed for other things than music. This is
       especially true if it has to run on an ARM2.
Note4: The terms 'custom note buffer' and '1-entry-per-voice buffer' used
       below refer to the buffer used to store notes triggered by some SWI's
       below before they are really played by the interrupt routine. Two
       notes played just one after each other probably means that only the
       lastest one will be taken into account. Some SWI's allow to solve that
       problem by controlling the empty state of the buffer.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SWI name         Nr !Entry                     !Exit/Effect
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Load             00 !R0=-1 to free RMA buffers !If an error occured, then
                    !or R0= 0 to load from     !   R0 points to error        
                    !         memory           !   and V is set,
                    !or R0 points to file name !else
                    !R1= source start address  !   R0= length of track
                    !    (if R0=0)             !       in memory.
                    !R2= 0 to load to RMA      !
                    !or R2= destination start  !
                    !       address            !
                    !R3= size of destination   !
                    !    buffer (if R2<>0)     !
                    !R4= 0 to claim buffer     !
                    !    in RMA                !
                    !or R4= start address of   !
                    !   buffer (32K space)     !
                    !A buffer address is needed only if the Symphony file
                    ! contains some packed data.
                    !Buffers are word aligned.
                    !In the case of packed data, the source and destination
                    ! buffers can't share any part of memory.
                    !In the case of entirely non packed data, the two buffers
                    ! can share a part of memory provided
                    ! destination address <= source address. After the call
                    ! the source data has been altered because the
                    ! module needs to build an internal structure different
                    ! to the source structure of the tune.
                    !Although the code is quite optimized, loading from
                    ! memory may take some time because all the data has to
                    ! be moved in memory. So don't expect loading 50 songs
                    ! per second with an ARM2!
--------------------+--------------------------+-----------------------------
RestartSong      01 ! -                        !Do a ResetParams,
                    !                          !Tune position set to (0,0),
                    !                          !Tune playing again.
--------------------+--------------------------+-----------------------------
Vol              02 !R0= new overall volume    !R0= previous overall volume
                    !    or -1 to read         !    (0-64).
                    !Initial value is 64       !
--------------------+--------------------------+-----------------------------
Stereo           03 !R0= voice number (0-7)    !R1= previous stereo position
                    !R1= new stereo position   !    (-127 to 127) for voice
                    !    or -128 to read       !    number R0.
                    !                          !
                    !Initial values are those of the Amiga.
--------------------+--------------------------+-----------------------------
CutNote          04 !R0= voice number (0-7)    !R1= previous note state on
                    !R1>=0 to read state       !    voice number R0
                    !  < 0 to stop note        !  < 0 -> stopped
                    !                          !  >=0 -> playing, = sample
                    !                          !         start address
                    !                          !If R1>=0 then
                    !                          !  R2= offset in sample
                    !                          !      in 1/(2^12) units
--------------------+--------------------------+-----------------------------
PlayInstrPacked  05 !R0= voice number (0-7)    !The new note is put into a
                    !R1= full note data        !1-entry-per-voice buffer to be
                    !R5= minimum sustain time  !played.
                    !    (in 1/50th sec)       !Setting a sustain time means
                    !R6<>0 to wait for buffer  !that the new note has
                    !      empty               !priority on the tune notes
                    !      else don't wait     !during this time.
--------------------+--------------------------+-----------------------------
PlayInstr        06 !R0= voice number (0-7)    !The new note is put into a
                    !R1= note number (0-36)    !1-entry-per-voice buffer to be
                    !R2= sample number (0-63)  !played.
                    !R3= effect number (0-63)  !Setting a sustain time means
                    !R4= effect value (0-&FFF) !that the new note has
                    !R5= minimum sustain time  !priority on the tune notes
                    !    (in 1/50th sec)       !during this time.
                    !R6<>0 to wait for buffer  !
                    !      empty               !
                    !      else don't wait     !
--------------------+--------------------------+-----------------------------
ResetParams      07 ! -                        !All parameters are reset
                    !                          !(stereo,counters,effects,...)
                    !                          !and do a FlushOutput.
--------------------+--------------------------+-----------------------------
FlushOutput      08 ! -                        !The current notes on all
                    !                          !channels are cut.
--------------------+--------------------------+-----------------------------
FreezeOutput     09 !R0= -1 to read output     !R0= previous output status
                    !        status            !(  0= off ie. no sound output
                    !   <>-1 to set            ! <>0= on )
--------------------+--------------------------+-----------------------------
UpCallVector     0A !R0= -1 to read upcall     !R0= previous upcall address
                    !       address            !
                    !  = -2 to set default     !
                    !  else new address        !
--------------------+--------------------------+-----------------------------
MaskVoice        0B !R0= voice number (0-7)    !R0= previous voice status
                    !R1= -1 to read voice stat !    (0= off, <>0=on)
                    !  <>-1 to set voice status!The notes are still played
                    !                          !but not heard for the voice.
--------------------+--------------------------+-----------------------------
SongPos          0C !R0= -1 to read sequence ps!R0= previous sequence pos
                    !  <>-1 to set             !R1= previous pattern pos
                    !R1= -1 to read pattern pos!    (0-63)
                    !  <>-1 to set             !If pattern pos is changed
                    !                          !then the current counter is
                    !                          !reset to play the tune line
                    !                          !as soon as possible.
--------------------+--------------------------+-----------------------------
TuneControl      0D !R0= -1 to read status     !R0= previous tune status
                    !  <>-1 to set (lower byte)!    (0= off, <>0= on)
                    !                          !Off means the tune decoder
                    !                          !won't let play notes anymore,
                    !                          !you can still play custom
                    !                          !notes.
                    !                          !Current notes still playing.
--------------------+--------------------------+-----------------------------
Pause            0E ! -                        !The tune is stopped and
                    !                          !current notes on tune
                    !                          !channels cut.
--------------------+--------------------------+-----------------------------
Voices           0F !R0= -1 to read hardware   !R0= previous hardware voices
                    !       voices number      !    number (1,2,4 or 8)
                    !  <>-1 to set voices      !
                    !The change is taken into account during next configure.
                    !Initial value is 4.
--------------------+--------------------------+-----------------------------
Wait             10 !R0= voice number (0-7)    !C is set if custom note
                    !                          !buffer is not empty,
                    !                          !else clear.
--------------------+--------------------------+-----------------------------
IntState         11 ! -                        !C is set if the call has
                    !                          !interrupted the playing or
                    !                          !filling routines.
--------------------+--------------------------+-----------------------------
NoteInfo         12 ! -                        !R0= address of current notes
                    !                          !    table (1 word per voice)
                    !                          !    note is 0 to 1023
                    !                          !R1= address of current
                    !                          !    samples table (1 byte per
                    !                          !    voice)
                    !                          !    sample is 0 to 63
                    !                          !R2= address of effects table
                    !                          !    (1 word per voice)
                    !                          !    bits 30-31 meaningless
                    !                          !    bits 16-21 effect nr
                    !                          !    bits  0-11 effect value
                    !                          !R3= address of volumes table
                    !                          !    (1 byte per voice)
                    !                          !    volume is 0 to 64
--------------------+--------------------------+-----------------------------
VuBar            13 !R0= voice number (0-7)    !R1= Vu bar height (0-64)
--------------------+--------------------------+-----------------------------
Loop             14 !R0= -1 to read loop contrl!R0= previous loop control
                    !  <>-1 to set             !    (  0= enabled,
                    !R1= -1 to read loop flag  !     <>0= disabled )
                    !  <>-1 to set             !R1<>0 if the tune has looped
                    !                          !      else not looped
                    !                          !
                    !Loop control is initially enabled.
                    !If a song has looped and the loop is disabled, you can
                    !continue playing using TuneControl.
--------------------+--------------------------+-----------------------------
BufferAddress    15 ! -                        !R0= current system hardware
                    !                          !    buffer address (with
                    !                          !    output data interleaved)
                    !                          !    208 bytes per channel
--------------------+--------------------------+-----------------------------
VuGravity        16 !R0= -1 to read Vu gravity !R0= previous gravity of Vu
                    !  <>-1 to set (lower byte)!    bars (0-255)
                    !Initial value is 2.       !
                    !The change is taken into account during next configure.
--------------------+--------------------------+-----------------------------
SampleRate       17 !R0= -1 to read sample rate!R0= previous sample rate
                    !  <>-1 to set             !    (0-99) - determines
                    !                          !    sample output density.
                    !Original value is 24.     !
                    !The change is taken into account during next configure.
--------------------+--------------------------+-----------------------------
Configure        18 !R0= -1 to reinstall previous
                    !       configuration      
                    !  <>-1 to configure the system
                    !       with new voices number,
                    !       sample rate, Vu gravity and hardware speed.
--------------------+--------------------------+-----------------------------
Params           19 !                          !R0= speed (1-&FFF)
                    !                          !R1= tempo (1-&FFF)
                    !                          !R2= counter (0-&FFE)
                    !The counter varies from 1 to speed-1 at a speed
                    !according to tempo (50 times a sec for default tempo)
--------------------+--------------------------+-----------------------------
TuneInfo         1A ! -                        !R0= tune length
                    !                          !R1= number of patterns
--------------------+--------------------------+-----------------------------
PlaySingle       1B !   R0= -1                 !   Play pattern R1
                    ! or                       ! or
                    !   R0<>-1                 !   Play from pos R0 to R1
                    !                          !
                    ! and                      !
                    !   R2= -1 for no loop     !
                    !     <>-1 to loop         !
                    !                          !
                    ! or R0=-1 and R1=-1       ! or Normal play.
                    !                          !
                    !                          !The pattern pos is set to 0.
                    !                          !In the case of playing a
                    !                          !part of the sequence, the
                    !                          !current position is set to
                    !                          !the first pos in that part.
--------------------+--------------------------+-----------------------------
DefaultStereo    1C !R0= voice number (0-7)    !R1= previous default stereo
                    !R1= new default stereo    !position (1 to 7) for
                    !    position              !voice number R0
                    !    or 0 to read          !
                    !                          !
                    !Initial values are those of the Amiga.
--------------------+--------------------------+-----------------------------
InstrData        1D !R0= sample number (1-63)  !The specs for sample R0
                    !R1= sample data address   !are changed to those on entry
                    !    or -1 to read         !R1= previous address
                    !R2= sample length         !R2= previous length
                    !    or -1 to read         !R3= previous repeat offset
                    !R3= repeat offset         !R4= previous repeat length
                    !    or -1 to read         !R5= previous volume
                    !R4= repeat length         !R6= previous finetune
                    !    or -1 to read         !    (-8 to 7)
                    !R5= volume (0-64)         !
                    !    or -1 to read         !
                    !R6= finetune (0-&F)       !
                    !    or -1 to read         !
                    !R1 to R4 must be 2-byte aligned.
                    !Put a repeat length of 0 for no repeats.
                    !Repeat length can't be 2.
                    !Set bit 31 of R1 if the sample is signed linear.
                    !The data is not moved i.e. it stays where you put it.
                    !The data is also scaled to the current machine volume if
                    !R1<>-1.
--------------------+--------------------------+-----------------------------
HardSpeed        1E !R0= samples output        !R0= previous parameter
                    !    frequency (in kHz)    !R1= current hardware speed
                    !    or 0 for 'auto speed' !    (in kHz)
                    !    or -1 to read         !The buffer filling routine
                    !                          !output frequency is changed
                    !                          !to the one on entry
                    !Initial mode is 24000     !
                    !The change is taken into account during next configure.
                    !
                    !In 'auto speed' mode, the filling routine will try to
                    !guess the current VIDC frequency for outputting samples
                    !by averaging the number of calls to it and adjust its
                    !tables to always have the same real pitch whatever the
                    !hardware speed is. The 'auto speed' selects one of the
                    !three following speeds currently:
                    !
                    !    24000 kHz (normal modes)
                    !    25175 kHz (VGA modes)
                    !    36000 kHz (multi sync modes)
                    !
                    !Too bad to have the same clock for graphics and sound!
--------------------+--------------------------+-----------------------------
LoopType         1F !R0= loop type             !R0= previous loop type
                    !   or -1 to read          !    (0 or 1)
                    !                          !
                    !Type 0: The loop flag is set if the tune reaches
                    !        position 0.
                    !Type 1: The loop flag is set if the tune jumps to
                    !        a lower position.
--------------------+--------------------------+-----------------------------
FillAddress      20 ! -                        !R0= address of buffer filling
                    !                          !    routine
--------------------+--------------------------+-----------------------------

So, with such a tool in the hands of (good) demo and game writers, we hope
to see more and more demos and games with decent (if not very good) sound,
and never listen again to the horrible *noises* made by previous (and some
current) lamer samples and SoundTrackers replayers!!!

Before giving our addresses, we'd like to thank the following people/groups
for their constructive remarks and questions and bug reports concerning
this player:

                                 SICK

                               ARMAXESS

                            George Saliaris


If you find any bug or have any comment about this player or even Digital
Symphony, don't hesitate to contact us at one of the addresses below:

        +----------------------------------------------------------------+
        !       You can contact the guys who made this software at       !
        +--------------------------+-------------------------------------+
        !    Bernard Jungen        !    Gil Damoiseaux                   !
        !    Friddericht 27        !    Rue du Bois des Broux 5          !
        !    B-6706 Autelbas       !    B-5080 Rhisnes                   !
        !    Belgium               !    Belgium                          !
        !                          !                                     !
        ! E-mail (until end 1999): !                                     !
        !    bju@cediti.be         !                                     !
        +--------------------------+-------------------------------------+

                      +----------------------------------+
                      ! John Tytgat                      !
                      ! Brusselbaan 445                  !
                      ! B-1600 St.-Pieters-Leeuw         !
                      ! Belgium                          !
                      !                                  !
                      ! E-mail:                          !
                      !  john.tytgat@barco.be            !
                      +----------------------------------+

If you would like to use our play routines in commercial products, or simply
want to buy Digital Symphony itself, then contact:

   +-------------------------------------------------------------------+
   ! You can obtain a fully multi-tasking sound tracker editor, called !
   ! Digital Symphony, which takes ProTracker, (Octo)MED, Tracker,     !
   !        Coconizer and native Symphony files as input from          !
   +-------------------------------------------------------------------+
   !                      Oregan Developments,                         !
   !                  36 Grosvenor Avenue, Streetly,                   !
   !                   Sutton Coldfield B74 3PE,                       !
   !                           England.                                !
   +-------------------------------------------------------------------+

© 1992/1996 B. Jungen & G. Damoiseaux (members of BASS).
